const db = require('../config/mysql');

class ProcurementPlanModel {
    constructor() {
        this.db = db;
        // 定义核心表名（与实际数据库一致）
        this.mainTable = 'goods_plan';         // 采购计划主表
        this.itemsTable = 'goods_plan_item';   // 采购计划明细表
        this.goodsTable = 'goods';             // 食材表
        this.supplierTable = 'supplier';       // 供应商表
        this.userTable = 'user';               // 申请人表（从外键推断）
        this.orderTable = "goods_order";       // 采购订单主表
        this.orderDetailTable = "goods_order_item";       // 采购订单详情明细表

    }

    /**
     * 获取所有采购计划（关联申请人信息，支持筛选和分页）
     * @param {Object} query - 筛选条件（状态、日期范围、分页）
     */
    async getAllPlans(query = {}) {
        let {
            status,
            startDate,
            endDate,
            goodsName,
            supplierId,
            page = 1,
            pageSize = 10
        } = query;
        console.log("查询参数：", query);
        const offset = (page - 1) * pageSize;

        // 1. 先查询符合条件的主计划ID（用于分页和关联明细）
        // 主计划ID查询SQL（带分页，用于限制主计划数量）
        let planIdsSql = `
            SELECT gp.plan_id
            FROM ${this.mainTable} gp
            LEFT JOIN ${this.itemsTable} gpi ON gp.plan_id = gpi.plan_id
            LEFT JOIN ${this.goodsTable} g ON gpi.goods_id = g.goods_id
            WHERE 1=1
        `;
        const planIdsParams = [];
        const mainConditions = [];

        // 条件筛选（与主查询共享）
        if (status !== undefined && status !== null && status !== '') {
            planIdsSql += ' AND gp.status = ?';
            mainConditions.push('gp.status = ?');
            planIdsParams.push(Number(status));
        }
        if (startDate) {
            planIdsSql += ' AND gp.plan_date >= ?';
            mainConditions.push('gp.plan_date >= ?');
            planIdsParams.push(startDate);
        }
        if (endDate) {
            planIdsSql += ' AND gp.plan_date <= ?';
            mainConditions.push('gp.plan_date <= ?');
            planIdsParams.push(endDate);
        }
        if (goodsName) {
            planIdsSql += ' AND g.name LIKE ?';
            mainConditions.push('g.name LIKE ?');
            planIdsParams.push(`%${goodsName}%`);
        }
        if (supplierId !== undefined && supplierId !== null && supplierId !== '') {
            planIdsSql += ' AND gpi.supplier_id = ?';
            mainConditions.push('gpi.supplier_id = ?');
            planIdsParams.push(Number(supplierId));
        }

        // 去重主计划ID并分页（核心：先限制主计划数量，再查明细）
        planIdsSql += ' GROUP BY gp.plan_id ORDER BY gp.created_at DESC LIMIT ?, ?';
        planIdsParams.push(offset, Number(pageSize));
        const [planIdsResult] = await this.db.query(planIdsSql, planIdsParams);
        const planIds = planIdsResult.map(item => item.plan_id); // 提取符合条件的主计划ID数组

        // 2. 查总数
        const countSql = `
            SELECT COUNT(DISTINCT gp.plan_id) AS total
            FROM ${this.mainTable} gp
            LEFT JOIN ${this.itemsTable} gpi ON gp.plan_id = gpi.plan_id
            LEFT JOIN ${this.goodsTable} g ON gpi.goods_id = g.goods_id
            WHERE 1=1
            ${mainConditions.length > 0 ? 'AND ' + mainConditions.join(' AND ') : ''}
        `;
        const countParams = planIdsParams.slice(0, planIdsParams.length - 2); // 排除分页参数
        const [countResult] = await this.db.query(countSql, countParams);
        const total = Number(countResult[0].total || 0);

        // 3. 如果没有主计划，直接返回空列表
        if (planIds.length === 0) {
            return {
                list: [],
                pagination: {
                    total,
                    page: Number(page),
                    pageSize: Number(pageSize),
                    totalPages: Math.ceil(total / pageSize)
                }
            };
        }

        // 注意：planIds起到的作用就是：根据查询条件过滤数据

        // 4. 批量查询主计划详情（通过ID过滤，已分页）
        const mainPlansSql = `
            SELECT 
                gp.plan_id,
                gp.code AS plan_code,
                gp.title AS plan_title,
                gp.plan_date,
                gp.urgency_level,
                gp.status,
                gp.created_uid,
                u.user_name AS creator_name,
                gp.created_at,
                gp.updated_at,
                gp.notes
            FROM ${this.mainTable} gp
            LEFT JOIN ${this.userTable} u ON gp.created_uid = u.user_id
            WHERE gp.plan_id IN (${planIds.map(() => '?').join(',')})
        `;
        const [mainPlans] = await this.db.query(mainPlansSql, planIds);

        // 5. 批量查询所有主计划对应的明细项（一次性查所有明细，减少数据库交互）
        const itemsSql = `
            SELECT 
                gpi.item_id,
                gpi.plan_id,
                gpi.goods_id,
                g.name AS goods_name,        -- 食材名称
                g.specification AS goods_spec, -- 食材规格
                g.unit AS goods_unit,        -- 食材单位
                gpi.supplier_id,
                s.supplier_name,             -- 供应商名称
                gpi.plan_count,              -- 计划数量
                gpi.price,                   -- 计划单价
                gpi.amount,                  -- 计划金额
                gpi.notes AS item_notes
            FROM ${this.itemsTable} gpi
            LEFT JOIN ${this.goodsTable} g ON gpi.goods_id = g.goods_id
            LEFT JOIN ${this.supplierTable} s ON gpi.supplier_id = s.supplier_id
            WHERE gpi.plan_id IN (${planIds.map(() => '?').join(',')})
        `;
        const [allItems] = await this.db.query(itemsSql, planIds);

        console.log("批量查询所有主计划对应的明细项（一次性查所有明细，减少数据库交互）::", allItems)

        // 注意：至此，所有的 主计划表 和 子计划表 中的 全部数据 都已经 经过“planIds”筛选 得到了  -- 仔细
        // 接下来就需要对上面的这 两块数据 进行处理了

        // 6. 组装数据：为主计划匹配对应的明细项
        const planMap = mainPlans.reduce((map, plan) => {
            map[plan.plan_id] = { ...plan, items: [] }; // 初始化每个主计划的items数组
            return map;
        }, {});  // 注意：利用reduce的累加机制

        /* planMap的数据类似：
        {
            1: { 
                plan_id: 1, 
                title: "日常采购计划", 
                ...其他主计划字段, 
                items: []  // 空数组，等待填充明细
            },
            2: { 
                plan_id: 2, 
                title: "紧急补货计划", 
                ...其他主计划字段, 
                items: [] 
            }
        }
        */

        // 给每个主计划分配明细项
        allItems.forEach(item => {
            if (planMap[item.plan_id]) {
                planMap[item.plan_id].items.push(item);
            }
        });

        console.log("给每个主计划分配明细项:", planMap)

        // 转换为数组并保持原排序（与planIds顺序一致）
        const resultList = planIds.map(planId => planMap[planId]);

        return {
            list: resultList,
            pagination: {
                total,
                page: Number(page),
                pageSize: Number(pageSize),
                totalPages: Math.ceil(total / pageSize)
            }
        };
    }

    /**
     * 根据ID获取采购计划详情（包含明细项、食材、供应商信息）
     * @param {number} planId - 采购计划ID（对应goods_plan.plan_id）
     */
    async getPlanById(planId) {
        // 1. 验证planId有效性
        if (!planId || isNaN(Number(planId))) {
            throw new Error('采购计划ID必须为有效的数字');
        }
        const targetPlanId = Number(planId);

        // 2. 批量查询主计划详情（复用getAllPlans中的主计划查询逻辑，确保字段一致）
        const mainPlanSql = `
            SELECT 
                gp.plan_id,
                gp.code AS plan_code,
                gp.title AS plan_title,
                gp.plan_date,
                gp.urgency_level,
                gp.status,
                gp.created_uid,
                u.user_name AS creator_name,
                gp.created_at,
                gp.updated_at,
                gp.notes
            FROM ${this.mainTable} gp
            LEFT JOIN ${this.userTable} u ON gp.created_uid = u.user_id
            WHERE gp.plan_id = ?
        `;

        // 3. 批量查询该主计划对应的明细项（与getAllPlans的明细项字段保持一致）
        const itemsSql = `
            SELECT 
                gpi.item_id,
                gpi.plan_id,
                gpi.goods_id,
                g.name AS goods_name,        -- 食材名称
                g.specification AS goods_spec, -- 食材规格
                g.unit AS goods_unit,        -- 食材单位
                gpi.supplier_id,
                s.supplier_name,             -- 供应商名称
                s.contact_person,            -- 供应商联系人（补充字段）
                s.phone AS supplier_phone,   -- 供应商电话（补充字段）
                gpi.plan_count,              -- 计划数量
                gpi.price,                   -- 计划单价
                gpi.amount,                  -- 计划金额
                gpi.notes AS item_notes
            FROM ${this.itemsTable} gpi
            LEFT JOIN ${this.goodsTable} g ON gpi.goods_id = g.goods_id
            LEFT JOIN ${this.supplierTable} s ON gpi.supplier_id = s.supplier_id
            WHERE gpi.plan_id = ?
            ORDER BY gpi.item_id ASC
        `;

        // 4. 并行执行查询（提升效率），组装数据
        return Promise.all([
            this.db.query(mainPlanSql, [targetPlanId]),
            this.db.query(itemsSql, [targetPlanId])
        ]).then(([
            [mainPlanResult],  // 主计划查询结果
            [itemsResult]      // 明细项查询结果
        ]) => {
            // 若主计划不存在，返回null
            if (mainPlanResult.length === 0) {
                return null;
            }

            // 组装主计划+明细项（与getAllPlans的返回结构完全一致）
            const planDetail = {
                ...mainPlanResult[0],
                items: itemsResult  // 明细项数组（与列表接口格式一致）
            };

            return planDetail;
        });
    }

    /**
     * 创建新的采购计划（包含明细项，事务保证一致性）
     * @param {Object} planData - 采购计划数据（主表+明细项）
     * @param {string} planData.title - 采购计划名称（必填）
     * @param {number} planData.createdUid - 申请人ID（必填）
     * @param {Array} planData.items - 明细项数组（必填，至少1条）
     * @param {string} [planData.planDate] - 采购日期（格式：YYYY-MM-DD，可选）
     * @param {number} [planData.urgencyLevel=1] - 紧急程度（1-普通，2-紧急，3-特急，可选）
     * @param {number} [planData.status=1] - 状态（1-待提交，2-审核中，可选）
     * @param {string} [planData.notes] - 计划备注（可选）
     */
    async createPlan(planData) {
        // 1. 严格参数校验（新增状态合法性校验）
        const validateErrors = [];
        // 采购计划名称校验
        if (!planData.title || typeof planData.title !== 'string' || planData.title.trim() === '') {
            validateErrors.push('采购计划名称必须为非空字符串');
        }
        // 申请人ID校验
        if (planData.createdUid === undefined || isNaN(Number(planData.createdUid))) {
            validateErrors.push('申请人ID必须为有效的数字');
        }
        // 状态合法性校验（只能是1-待提交或2-待生成）
        const allowedStatus = [1, 2]; // 允许的状态值
        if (planData.status !== undefined) { // 若用户传入了status
            const statusNum = Number(planData.status);
            if (isNaN(statusNum) || !allowedStatus.includes(statusNum)) {
                validateErrors.push(`状态只能是${allowedStatus.join('或')}（1-待提交，2-待生成）`);
            }
        }
        // 明细项校验
        if (!Array.isArray(planData.items) || planData.items.length === 0) {
            validateErrors.push('明细项必须为非空数组，至少包含1条记录');
        } else {
            planData.items.forEach((item, index) => {
                if (item.goodsId === undefined || isNaN(Number(item.goodsId))) {
                    validateErrors.push(`第${index + 1}条明细：食材ID必须为有效的数字`);
                }
                if (item.planCount === undefined || isNaN(Number(item.planCount)) || Number(item.planCount) <= 0) {
                    validateErrors.push(`第${index + 1}条明细：计划数量必须为大于0的数字`);
                }
            });
        }
        // 校验申请人是否存在
        const [userResult] = await this.db.query(
            `SELECT user_id FROM ${this.userTable} WHERE user_id = ?`,
            [Number(planData.createdUid)]
        );
        if (userResult.length === 0) {
            validateErrors.push(`申请人ID不存在：${planData.createdUid}`);
        }
        // 抛出所有校验错误
        if (validateErrors.length > 0) {
            throw new Error(`参数校验失败：${validateErrors.join('；')}`);
        }

        // 2. 手动管理事务（不依赖 transaction 方法）
        let connection; // 声明连接变量，用于后续释放
        try {
            // 2.1 从连接池获取一个连接
            connection = await this.db.getConnection();

            // 2.2 开启事务
            await connection.beginTransaction();

            // 3. 生成唯一业务单号（逻辑不变）
            const dateStr = new Date().toISOString().slice(0, 10).replace(/-/g, ''); // 格式：YYYYMMDD
            const [maxCodeResult] = await connection.query(
                `SELECT code FROM ${this.mainTable} WHERE code LIKE ? ORDER BY code DESC LIMIT 1`,
                [`PC${dateStr}%`]
            );
            let sequence = 1;
            if (maxCodeResult.length > 0) {
                const lastCode = maxCodeResult[0].code;
                sequence = Number(lastCode.slice(-3)) + 1;
            }
            const planCode = `PC${dateStr}${String(sequence).padStart(3, '0')}`;

            // 4. 插入主计划（状态默认值为1-待提交，若用户传入合法状态则使用）
            const planSql = `
                INSERT INTO ${this.mainTable} 
                (code, title, plan_date, urgency_level, status, created_uid, updated_uid, created_at, updated_at, notes) 
                VALUES (?, ?, ?, ?, ?, ?, ?, NOW(), NOW(), ?)
            `;
            // 处理状态值：若用户传入合法状态则使用，否则默认1-待提交
            const statusValue = planData.status !== undefined
                ? Number(planData.status)
                : 1;
            const [planResult] = await connection.query(planSql, [
                planCode,
                planData.title.trim(),
                planData.planDate ? new Date(planData.planDate) : new Date(),
                planData.urgencyLevel ? Number(planData.urgencyLevel) : 1,
                statusValue, // 使用校验后的状态值
                Number(planData.createdUid),
                Number(planData.createdUid),
                planData.notes || ''
            ]);
            const newPlanId = planResult.insertId;

            // 5. 插入明细项（逻辑不变）
            const itemsValues = planData.items.map(item => {
                const price = item.price !== undefined ? Number(item.price) : 0;
                const planCount = Number(item.planCount);
                const amount = item.amount !== undefined
                    ? Number(item.amount)
                    : Number((planCount * price).toFixed(2));

                return [
                    newPlanId,
                    Number(item.goodsId),
                    item.supplierId !== undefined ? Number(item.supplierId) : null,
                    planCount,
                    price || null,
                    amount,
                    item.notes || ''
                ];
            });
            const itemsSql = `
                INSERT INTO ${this.itemsTable} 
                (plan_id, goods_id, supplier_id, plan_count, price, amount, notes) 
                VALUES ?
            `;
            const [itemsResult] = await connection.query(itemsSql, [itemsValues]);

            // 6. 提交事务
            await connection.commit();

            // 7. 返回创建结果
            return {
                planId: newPlanId,
                planCode: planCode,
                status: statusValue, // 返回实际使用的状态值
                mainAffectedRows: planResult.affectedRows,
                itemsAffectedRows: itemsResult.affectedRows,
                totalItems: planData.items.length
            };

        } catch (error) {
            // 8. 错误回滚
            if (connection) {
                await connection.rollback();
            }
            console.error(`创建采购计划失败：${error.message}`, { planData });
            throw new Error(`创建采购计划失败：${error.message}`);

        } finally {
            // 9. 释放连接
            if (connection) {
                connection.release();
            }
        }
    }

    /*
    在创建采购计划的场景中，必须开启事务，原因是这个操作涉及到两个相互关联的数据库写操作：
        向主表 goods_plan 插入采购计划记录
        向明细表 goods_plan_item 插入该计划对应的明细项
    这两个操作是原子性的（要么同时成功，要么同时失败），否则会导致数据不一致。
    */

    /**
     * 更新采购计划（支持全量更新明细项，事务保证一致性）
     * @param {number} planId - 采购计划ID
     * @param {Object} planData - 待更新数据（主表+可选明细项）
     * @param {string} [planData.title] - 采购计划名称（可选）
     * @param {string} [planData.planDate] - 采购日期（格式：YYYY-MM-DD，可选）
     * @param {number} [planData.urgencyLevel] - 紧急程度（1-普通，2-紧急，3-特急，可选）
     * @param {number} [planData.status] - 状态（1-待提交，2-审核中，可选）
     * @param {string} [planData.notes] - 计划备注（可选）
     * @param {Array} [planData.items] - 明细项数组（可选，全量更新时传入）
     */
    async updatePlan(planId, planData) {
        // 1. 基础参数校验
        const validateErrors = [];
        // 校验planId有效性
        if (isNaN(Number(planId)) || Number(planId) <= 0) {
            validateErrors.push('采购计划ID必须为有效的正整数');
        }
        // 若传入明细项，校验明细格式
        if (planData.items !== undefined) {
            if (!Array.isArray(planData.items)) {
                validateErrors.push('明细项必须为数组类型');
            } else {
                planData.items.forEach((item, index) => {
                    if (item.goodsId === undefined || isNaN(Number(item.goodsId)) || Number(item.goodsId) <= 0) {
                        validateErrors.push(`第${index + 1}条明细：食材ID必须为有效的正整数`);
                    }
                    if (item.planCount === undefined || isNaN(Number(item.planCount)) || Number(item.planCount) <= 0) {
                        validateErrors.push(`第${index + 1}条明细：计划数量必须为大于0的数字`);
                    }
                });
            }
        }
        // 校验申请人ID（如果传入了createdUid，需验证存在性）
        if (planData.createdUid !== undefined) {
            if (isNaN(Number(planData.createdUid))) {
                validateErrors.push('申请人ID必须为有效的数字');
            } else {
                const [userResult] = await this.db.query(
                    `SELECT user_id FROM ${this.userTable} WHERE user_id = ?`,
                    [Number(planData.createdUid)]
                );
                if (userResult.length === 0) {
                    validateErrors.push(`申请人ID不存在：${planData.createdUid}`);
                }
            }
        }
        if (validateErrors.length > 0) {
            throw new Error(`参数校验失败：${validateErrors.join('；')}`);
        }

        // 2. 验证计划是否存在
        const existingPlan = await this.getPlanById(Number(planId));
        if (!existingPlan) {
            throw new Error(`采购计划ID=${planId}不存在`);
        }

        // 3. 手动管理事务（不依赖transaction方法）
        let connection;
        try {
            // 3.1 获取连接并开启事务
            connection = await this.db.getConnection();
            await connection.beginTransaction();

            // 4. 更新主计划（只更新传入的有效字段）
            const updateFields = [];
            const updateParams = [];

            if (planData.title !== undefined) {
                updateFields.push('title = ?');
                updateParams.push(planData.title.trim()); // 去空格处理
            }
            if (planData.planDate !== undefined) {
                updateFields.push('plan_date = ?');
                updateParams.push(new Date(planData.planDate)); // 转换为日期对象
            }
            if (planData.urgencyLevel !== undefined) {
                updateFields.push('urgency_level = ?');
                updateParams.push(Number(planData.urgencyLevel));
            }
            if (planData.status !== undefined) {
                updateFields.push('status = ?');
                updateParams.push(Number(planData.status));
            }
            if (planData.createdUid !== undefined) {
                updateFields.push('created_uid = ?'); // 允许更新申请人（如果业务需要）
                updateParams.push(Number(planData.createdUid));
            }
            if (planData.notes !== undefined) {
                updateFields.push('notes = ?');
                updateParams.push(planData.notes);
            }

            // 若有字段需要更新，执行UPDATE
            if (updateFields.length > 0) {
                const planSql = `
                    UPDATE ${this.mainTable} 
                    SET ${updateFields.join(', ')}, updated_at = NOW() 
                    WHERE plan_id = ?
                `;
                updateParams.push(Number(planId)); // 补充WHERE条件的plan_id
                await connection.query(planSql, updateParams);
            }

            // 5. 处理明细项（全量更新：先删除原有，再插入新的）
            if (planData.items !== undefined) {
                // 5.1 删除该计划的所有旧明细
                await connection.query(
                    `DELETE FROM ${this.itemsTable} WHERE plan_id = ?`,
                    [Number(planId)]
                );

                // 5.2 插入新明细（如果数组非空）
                if (planData.items.length > 0) {
                    const itemsValues = planData.items.map(item => {
                        const price = item.price !== undefined ? Number(item.price) : 0;
                        const planCount = Number(item.planCount);
                        // 金额计算规则与创建接口保持一致
                        const amount = item.amount !== undefined
                            ? Number(item.amount)
                            : Number((planCount * price).toFixed(2));

                        return [
                            Number(planId),
                            Number(item.goodsId),
                            item.supplierId !== undefined ? Number(item.supplierId) : null,
                            planCount,
                            price || null,
                            amount,
                            item.notes || ''
                        ];
                    });
                    const itemsSql = `
                        INSERT INTO ${this.itemsTable} 
                        (plan_id, goods_id, supplier_id, plan_count, price, amount, notes) 
                        VALUES ?
                    `;
                    await connection.query(itemsSql, [itemsValues]);
                }
            }

            // 6. 提交事务
            await connection.commit();

            // 7. 返回更新结果（包含更新后的计划ID和明细项数量）
            return {
                planId: Number(planId),
                updatedFields: updateFields.length,
                totalItems: planData.items?.length || existingPlan.items.length // 若未更新明细，返回原数量
            };

        } catch (error) {
            // 8. 出错时回滚事务
            if (connection) {
                await connection.rollback();
            }
            console.error(`更新采购计划失败：${error.message}`, { planId, planData });
            throw new Error(`更新采购计划失败：${error.message}`);

        } finally {
            // 9. 释放连接
            if (connection) {
                connection.release();
            }
        }
    }

    /**
     * 删除采购计划（级联删除明细项，事务保证）
     * @param {number} planId - 采购计划ID
     */
    async deletePlan(planId) {
        // 校验计划是否存在
        const existingPlan = await this.getPlanById(planId);
        if (!existingPlan) {
            throw new Error(`采购计划ID=${planId}不存在`);
        }

        return await this.db.transaction(async (conn) => {
            // 1. 先删除明细项（外键约束：必须先删子表）
            await conn.query(`DELETE FROM ${this.itemsTable} WHERE plan_id = ?`, [planId]);

            // 2. 再删除主计划
            const [result] = await conn.query(`DELETE FROM ${this.mainTable} WHERE plan_id = ?`, [planId]);
            return {
                planId,
                deletedRows: result.affectedRows
            };
        });
    }

    /**
     * 更新采购计划状态（适配 mysql2 Promise 连接池）
     * 计划状态：1-待审核, 2-待提交采购订单, 3-已生成订单, 0-已作废
     */
    async updatePlanStatus(planId, status, operatorId, remark = '') {
        try {
            // 1. 参数校验（保持不变）
            const validateErrors = [];
            const validStatus = [1, 2, 3, 0];
            const statusTextMap = { 1: '待审核', 2: '待提交采购订单', 3: '已生成订单', 0: '已作废' };

            if (isNaN(Number(planId)) || Number(planId) <= 0) {
                validateErrors.push('采购计划ID必须为有效的正整数');
            }
            const targetStatus = Number(status);
            if (!validStatus.includes(targetStatus)) {
                validateErrors.push(`无效状态值：${status}，允许值：${validStatus.map(s => `${s}(${statusTextMap[s]})`).join(', ')}`);
            }
            if (isNaN(Number(operatorId)) || Number(operatorId) <= 0) {
                validateErrors.push('操作人ID必须为有效的正整数');
            }

            // 校验操作人是否存在（使用 promisePool 的 query 直接调用）
            const [operatorResult] = await this.db.query(
                `SELECT user_id FROM ${this.userTable} WHERE user_id = ?`,
                [Number(operatorId)]
            );
            if (operatorResult.length === 0) {
                validateErrors.push(`操作人ID不存在：${operatorId}`);
            }
            if (validateErrors.length > 0) {
                throw new Error(`参数校验失败：${validateErrors.join('；')}`);
            }

            // 2. 校验计划存在性
            const existingPlan = await this.getPlanById(Number(planId));
            if (!existingPlan) {
                throw new Error(`采购计划ID=${planId}不存在`);
            }
            const currentStatus = existingPlan.status;

            // 3. 状态流转校验
            const validTransitions = {
                1: [2, 0],
                2: [3, 1, 0],
                3: [0],
                0: []
            };
            if (!validTransitions[currentStatus].includes(targetStatus)) {
                throw new Error(`状态流转不合法：不允许从「${statusTextMap[currentStatus]}」变更为「${statusTextMap[targetStatus]}」`);
            }

            // 4. 执行更新操作
            let result;
            if (targetStatus === 3) {
                // 使用 mysql2 promise 连接池的事务处理
                const connection = await this.db.getConnection(); // 获取连接（Promise 方式）
                try {
                    // 开始事务
                    await connection.beginTransaction();

                    // 更新采购计划状态
                    const [updateResult] = await connection.query(
                        `UPDATE ${this.mainTable} 
                        SET status = ?, updated_at = NOW(), updated_uid = ?
                        WHERE plan_id = ?`,
                        [
                            targetStatus,
                            Number(operatorId),
                            Number(planId)
                        ]
                    );

                    // 创建采购订单及详情（传递 connection 给子方法）
                    const orderResult = await this.createPurchaseOrder(connection, existingPlan, operatorId);

                    // 提交事务
                    await connection.commit();

                    result = {
                        msg:"此订单已经同步至采购订单",
                        success: true,
                        planId: Number(planId),
                        oldStatus: currentStatus,
                        oldStatusText: statusTextMap[currentStatus],
                        newStatus: targetStatus,
                        newStatusText: statusTextMap[targetStatus],
                        operatorId: Number(operatorId),
                        affectedRows: updateResult.affectedRows,
                        orderId: orderResult.orderId,
                        orderDetailsCount: orderResult.detailsCount
                    };

                } catch (error) {
                    // 回滚事务
                    await connection.rollback();
                    throw new Error(`事务处理失败：${error.message}`);
                } finally {
                    // 释放连接（mysql2 连接池的连接必须手动释放）
                    connection.release();
                }
            } else {
                // 非生成订单状态直接更新（使用 promise 连接池的 query）
                const [updateResult] = await this.db.query(
                    `UPDATE ${this.mainTable} 
                    SET status = ?, updated_at = NOW(), updated_uid = ?
                    WHERE plan_id = ?`,
                    [
                        targetStatus,
                        Number(operatorId),
                        Number(planId)
                    ]
                );

                result = {
                    success: true,
                    planId: Number(planId),
                    oldStatus: currentStatus,
                    oldStatusText: statusTextMap[currentStatus],
                    newStatus: targetStatus,
                    newStatusText: statusTextMap[targetStatus],
                    operatorId: Number(operatorId),
                    affectedRows: updateResult.affectedRows
                };
            }

            return result;
        } catch (error) {
            console.error('updatePlanStatus 错误:', error);
            return {
                success: false,
                message: error.message,
                planId: planId ? Number(planId) : null
            };
        }
    }

    /**
     * 创建采购订单及详情（适配 mysql2 Promise 连接）
     * @param {object} connection - mysql2 的连接对象（带事务）
     * @param {object} plan - 采购计划信息
     * @param {number} operatorId - 操作人ID
     */
    async createPurchaseOrder(connection, plan, operatorId) {
        try {
            // 1. 获取采购计划详情（直接使用plan.items，无需再次查询数据库）
            const planDetails = plan.items || [];
            if (planDetails.length === 0) {
                throw new Error(`采购计划ID=${plan.plan_id}没有关联的计划详情，无法生成订单`);
            }

            // 2. 从计划详情中提取供应商ID（优先取第一个有供应商ID的明细）
            let supplierId = null;
            for (const item of planDetails) {
                if (item.supplier_id && !isNaN(Number(item.supplier_id)) && Number(item.supplier_id) > 0) {
                    supplierId = Number(item.supplier_id);
                    break; // 找到第一个有效供应商ID后停止
                }
            }
            // 校验供应商ID有效性
            if (isNaN(supplierId) || supplierId <= 0) {
                throw new Error(`采购计划ID=${plan.plan_id}的所有明细均无有效供应商ID，无法生成订单`);
            }

            // 3. 生成订单业务单号（格式：PO+日期+3位序号，如PO20251025001）
            const dateStr = new Date().toISOString().slice(0, 10).replace(/-/g, ''); // 20251025
            const [maxCodeResult] = await connection.query(
                `SELECT code FROM ${this.orderTable} WHERE code LIKE ? ORDER BY code DESC LIMIT 1`,
                [`PO${dateStr}%`]
            );
            let seq = 1;
            if (maxCodeResult.length > 0) {
                const lastSeq = Number(maxCodeResult[0].code.slice(-3));
                seq = lastSeq + 1;
            }
            const orderCode = `PO${dateStr}${seq.toString().padStart(3, '0')}`;

            // 4. 计算订单总金额（累加计划明细的 数量*单价，保留2位小数）
            let totalAmount = 0;
            for (const item of planDetails) {
                const planCount = Number(item.plan_count) || 0;
                const price = Number(item.price) || 0;
                totalAmount += planCount * price;
            }
            totalAmount = Number(totalAmount.toFixed(2)); // 适配decimal(12,2)

            // 5. 插入采购订单主表（goods_order）
            const [orderResult] = await connection.query(
                `INSERT INTO ${this.orderTable} (
                    code,          -- 订单业务单号
                    plan_id,       -- 关联采购计划ID
                    order_date,    -- 订单创建时间
                    total_amount,  -- 总金额
                    status,        -- 状态：1-待发货
                    created_uid,   -- 创建人ID
                    updated_uid,   -- 更新人ID
                    notes,         -- 从前表带过来
                    created_at,    -- 创建时间
                    updated_at     -- 更新时间
                ) VALUES (?, ?, NOW(), ?, 1, ?, ?, ?, NOW(), NOW())`,
                [
                    orderCode,
                    plan.plan_id,
                    totalAmount,
                    operatorId,
                    operatorId,
                    plan.notes
                ]
            );
            const orderId = orderResult.insertId;

            // 6. 批量插入订单详情（goods_order_item，移除unit字段）
            const detailValues = planDetails.map(detail => {
                const orderedCount = Number(detail.plan_count) || 0;
                const unitPrice = Number(detail.price) || 0;
                const amount = Number((orderedCount * unitPrice).toFixed(2));
                return [
                    orderId,               // 所属订单ID
                    detail.item_id,        // 关联的计划明细ID（plan_item_id）
                    detail.goods_id,       // 商品ID
                    orderedCount,          // 订购数量（ordered_count）
                    unitPrice,             // 单价（unit_price）
                    amount,                // 金额（amount）
                    detail.item_notes || '' // 备注（notes，可选）
                ];
            });

            const [detailsResult] = await connection.query(
                `INSERT INTO ${this.orderDetailTable} (
                    order_id,        -- 所属订单ID
                    plan_item_id,    -- 关联计划明细ID
                    goods_id,        -- 商品ID
                    ordered_count,   -- 订购数量
                    unit_price,      -- 单价
                    amount,          -- 金额
                    notes            -- 备注（可选）
                ) VALUES ?`,
                [detailValues]
            );

            return {
                orderId,
                orderCode,
                detailsCount: detailsResult.affectedRows
            };
        } catch (error) {
            console.error(`生成订单失败（计划ID=${plan.plan_id}）：`, error);
            throw new Error(`创建订单及详情失败：${error.message}`);
        }
    }
}

module.exports = ProcurementPlanModel;